package com.example.utility.crypto.sm3;

/**
 * @author 季舟
 * @Date 2024-12-27 16:37
 */

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;

public class SM3Demo {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static void main(String[] args) throws Exception {

        // 待哈希的数据
        String originalData = "Hello, SM3!";

        // 生成SM3哈希值
        byte[] hash = generateSM3Hash(originalData);

        // 将哈希值转换为十六进制字符串以便显示
        String hashHex = Hex.toHexString(hash);
        System.out.println("SM3 Hash: " + hashHex);

        // 验证哈希值
        boolean isValid = verifySM3Hash(originalData, hash);
        System.out.println("Hash is valid: " + isValid);
    }


    /**
     * 生成SM3哈希值
     * 该方法接收原始数据字符串，使用SM3哈希算法生成哈希值，并返回哈希值的字节数组
     * 使用Bouncy Castle作为安全提供者来实现SM3哈希算法
     *
     * @param originalData 原始数据字符串，用于生成哈希值
     * @return 返回使用SM3算法生成的哈希值的字节数组
     * @throws NoSuchAlgorithmException 如果找不到SM3算法，则抛出此异常
     * @throws NoSuchProviderException  如果找不到Bouncy Castle提供者，则抛出此异常
     */
    public static byte[] generateSM3Hash(String originalData) throws NoSuchAlgorithmException, NoSuchProviderException {

        // 将原始数据转换为字节数组
        byte[] data = originalData.getBytes();

        // 获取MessageDigest实例，指定使用SM3算法和Bouncy Castle提供者
        MessageDigest md = MessageDigest.getInstance("SM3", BouncyCastleProvider.PROVIDER_NAME);

        // 使用指定的字节数组更新MessageDigest实例，并返回计算得到的哈希值的字节数组
        return md.digest(data);
    }


    /**
     * 验证SM3哈希值是否匹配
     * 此方法用于校验给定的原始数据的SM3哈希值是否与预期的哈希值一致
     * 它首先计算原始数据的SM3哈希值，然后使用MessageDigest的isEqual方法比较计算出的哈希值和预期的哈希值
     * 使用SM3哈希算法可以确保数据的完整性，即确保数据未被篡改
     *
     * @param originalData 原始数据字符串，用于生成哈希值
     * @param expectedHash 预期的哈希值，与原始数据的哈希值进行比较
     * @return 如果计算出的哈希值与预期的哈希值匹配，则返回true；否则返回false
     * @throws NoSuchAlgorithmException 如果找不到SM3哈希算法，则抛出此异常
     * @throws NoSuchProviderException 如果没有提供者支持SM3哈希算法，则抛出此异常
     */
    public static boolean verifySM3Hash(String originalData, byte[] expectedHash) throws NoSuchAlgorithmException, NoSuchProviderException {

        // 计算原始数据的SM3哈希值
        byte[] actualHash = generateSM3Hash(originalData);

        // 比较计算出的哈希值和预期的哈希值
        return MessageDigest.isEqual(actualHash, expectedHash);
    }
}

